<?php
class WPCOS {
    public $options;
    public $bucket;
    public $host;

    function __construct($bucket='') {
        $this->options = get_option('wp_cos');
		$this->options = unserialize($this->options);
        switch($bucket) {
            case 'upload' :
                $this->bucket = $this->options['bucket_upload'];
                break;
            case 'backup' :
                $this->bucket = $this->options['bucket_backup'];
                break;
            default:
                $this->bucket = $bucket;
        }
        $this->host = $this->host();
    }

    //处理xml数据
    private function xml2array($data) {
        $xml = simplexml_load_string($data);
        $xml = json_encode($xml);
        $xml = json_decode($xml, true);
        return $xml;
    }

    //处理参数
    private function keylist($data, $type='headers') {
        $keylist = array();
        foreach($data as $key=>$val) {
            if('headers' == $type) {
                $key = urlencode($key);
                $val = rawurlencode($val);
            }

            $key = strtolower($key);
            $keylist[$key] = $key . '=' . $val;
        }
        ksort($keylist);
        return $keylist;
    }

    //签名
    private function sign($headers, $urlparams=array(), $object_key='/', $method='GET') {
        $keytime = (string) wp_date('U', (time()-60)) . ';' . (string) wp_date('U', (time()+30*60));
        if($urlparams) {
            $urlparams = $this->keylist($urlparams, 'url');
            $urlparamlist = join(';', array_keys($urlparams));
            $httpparameters = join('&', array_values($urlparams));
        } else {
            $urlparamlist = $httpparameters = '';
        }

        $headers = $this->keylist($headers);
        $headerlist = join(';', array_keys($headers));
        $httpheaders = join('&', array_values($headers));

        $httpstring = join("\n", [
            strtolower($method),
            $object_key,
            $httpparameters,
            $httpheaders,
            ''
        ]);

        $stringtosign = join("\n", [
            'sha1',
            $keytime,
            sha1($httpstring),
            ''
        ]);

        $signkey = hash_hmac('sha1', $keytime, $this->options['secret_key']);
        $signature = hash_hmac('sha1', $stringtosign, $signkey);

        $authorization = join('&', [
            'q-sign-algorithm=sha1',
            'q-ak=' . $this->options['secret_id'],
            'q-sign-time=' . $keytime,
            'q-key-time=' . $keytime,
            'q-header-list=' . $headerlist,
            'q-url-param-list=' . $urlparamlist,
            'q-signature=' . $signature
        ]);
        return $authorization;
    }

    //获取所有Bucket
    public function buckets() {
        $host = 'service.cos.myqcloud.com';
        $url = 'https://' . $host;
        $headers = array(
            'Host' => $host,
            'Date' => wp_date('r'),
        );
        $authorization = $this->sign($headers);
        $headers['Authorization'] = $authorization;

        $response = wp_remote_get($url, array(
            'headers' => $headers,
            'sslverify' => true,
        ));

        if(is_wp_error($response)) {
            return [];
        }

        $code = wp_remote_retrieve_response_code($response);

        if(200 != $code) {
            return [];
        }

        return $this->xml2array($response['body']);
    }

    //获取地域
    public function get_bucket_region() {
        $region = '';
        $buckets = $this->buckets();
        if(!empty($buckets['Buckets']['Bucket'])) {
            foreach($buckets['Buckets']['Bucket'] as $val) {
                if($this->bucket . '-' . $this->options['appid'] == $val['Name']) {
                    $region = $val['Location'];
                    break;
                }
            }
        }

        return $region;
    }

    //获取Host
    private function host() {
        $region = $this->get_bucket_region();
        return $this->bucket . '-' . $this->options['appid'] . '.cos.' . $region . '.myqcloud.com';
    }

    //上传
    public function upload($target, $file, $args=array()) {
        if(!$target || $target == '/' || $target == '.') {
            return 'Object Key不能为空';
        }
        $target = '/' . ltrim($target, '/');
        $url = 'https://' . $this->host . $target;
        $headers = array(
            'Host' => $this->host,
            'Date' => wp_date('r'),
            'Content-Type' => mime_content_type($file),
            'Content-Length' => filesize($file),
            'Content-MD5' => base64_encode(md5_file($file, true)),
        );
        $authorization = $this->sign($headers, '', $target, 'PUT');
        $headers['Authorization'] = $authorization;
        if($args) {
            $headers = wp_parse_args($args, $headers);
        }
 
        $response = wp_remote_request($url, array(
            'method' => 'PUT',
            'timeout' => 600,
            'headers' => $headers,
            'sslverify' => true,
            'body' => file_get_contents($file),
        ));


        if(is_wp_error($response)) {
            return $response->get_error_message();
        }

        $code = wp_remote_retrieve_response_code($response);

        if(200 != $code || isset($xml['Message'])) {
            $xml = $this->xml2array($response['body']);
            return $xml['RequestId'] . '：' . $xml['Message'];
        }

        if(isset($headers['Pic-Operations'])) {
            if(empty($response['body'])) {
                return '没有返回数据';
            }
            return $this->xml2array($response['body']);
        }

        return true;
    }

    //复制对象
    public function copy($target, $newkey) {
        if(!$target || $target == '/' || $target == '.' 
            || !$newkey || $newkey == '/' || $newkey == '.') {
            return 'Object Key不能为空';
        }
        $target = ltrim($target, '/');
        $newkey = '/' . ltrim($newkey, '/');
        $url = 'https://' . $this->host . $newkey;
        $headers = array(
            'Host' => $this->host,
            'Date' => wp_date('r'),
        );
        $authorization = $this->sign($headers, '', $newkey, 'PUT');
        $headers['Authorization'] = $authorization;
        $headers['x-cos-copy-source'] = $this->host . '/' . urlencode($target);

        $response = wp_remote_request($url, array(
            'method' => 'PUT',
            'headers' => $headers,
            'sslverify' => true
        ));


        if(is_wp_error($response)) {
            return $response->get_error_message();
        }

        $xml = $this->xml2array($response['body']);
        if(isset($xml['Message'])) {
            return $xml['RequestId'] . '：' . $xml['Message'];
        }

        return true;
    }

    //删除对象
    public function delete($target) {
        if(!$target || $target == '/' || $target == '.') {
            return 'Object Key不能为空';
        }
        $target = '/' . ltrim($target, '/');
        $url = 'https://' . $this->host . $target;
        $headers = array(
            'Host' => $this->host,
            'Date' => wp_date('r'),
        );
        $authorization = $this->sign($headers, '', $target, 'DELETE');
        $headers['Authorization'] = $authorization;

        $response = wp_remote_request($url, array(
            'method' => 'DELETE',
            'headers' => $headers,
            'sslverify' => true
        ));

        if(is_wp_error($response)) {
            return $response->get_error_message();
        }

        return true;
    }

    //获取对象
    public function get_object($object_key) {
        if(!$object_key || $object_key == '/' || $object_key == '.') {
            return '';
        }
        $object_key = '/' . ltrim($object_key, '/');
        $url = 'https://' . $this->host . $object_key;
        $headers = array(
            'Host' => $this->host,
            'Date' => wp_date('r'),
        );
        $authorization = $this->sign($headers, '', $object_key);
        $headers['Authorization'] = $authorization;

        $response = wp_remote_get($url, array(
            'headers' => $headers,
            'sslverify' => true,
        ));

        if(is_wp_error($response)) {
            return '';
        }
        
        $code = wp_remote_retrieve_response_code($response);

        if(200 == $code) {
            return $response['body'];
        }

        return '';
    }

    //云端数据处理请求
    private function image_processing_request($url, $headers, $pic_operations) {
        $headers['Pic-Operations'] = json_encode($pic_operations, JSON_UNESCAPED_UNICODE);
        $response = wp_remote_post($url, array(
            'headers' => $headers,
            'sslverify' => true,
        ));

        if(is_wp_error($response)) {
            return $response->get_error_message();
        }

        $code = wp_remote_retrieve_response_code($response);

        $xml = $this->xml2array($response['body']);
        if(200 != $code) {
            //return $xml['RequestId'] . '：' . $xml['Message'];
        } else {
            return $xml;
        }
    }

    //云端数据处理
    public function image_processing($target, $type='') {
        if(!$target || $target == '/' || $target == '.') {
            return;
        }
        $target = '/' . ltrim($target, '/');
        $pathinfo = pathinfo($target);
        $pathinfo['extension'] = isset($pathinfo['extension']) ? strtolower($pathinfo['extension']) : '';
        $url = 'https://' . $this->host . $target . '?image_process';
        $pic_operations['is_pic_info'] = 1;
        $headers = array(
            'Host' => $this->host,
            'Date' => wp_date('r'),
        );
        $urlparams = array('image_process'=>'');
        $authorization = $this->sign($headers, $urlparams, $target, 'POST');
        $headers['Authorization'] = $authorization;

        $request = null;
        if($this->options['image_style'] && (!$type || 'image_style' == $type)) {
            $pic_operations['rules'] = array([
                'fileid' => $target,
                'rule' => 'style/' . $this->options['image_style'],
            ]);
            $request = $this->image_processing_request($url, $headers, $pic_operations);
        }

        if('on' == $this->options['image_compress'] && (!$type || 'image_compress' == $type)) {
            $pic_operations['rules'] = array([
                'fileid' => $target,
                'rule' => 'imageMogr2/format/webp',
            ]);
            $request = $this->image_processing_request($url, $headers, $pic_operations);  
        }

        if(!$type || 'watermark' == $type) {
            if('image' == $this->options['watermark']) {
                $pic_operations['rules'] = array([
                    'fileid' => $target,
                    'rule' => 'watermark/3/type/2/image/' . base64_encode('http://' . $this->host . '/watermark.png'),
                ]);
                $request = $this->image_processing_request($url, $headers, $pic_operations); 
            }
    
            if('text' == $this->options['watermark'] && $this->options['watermark_text']) {
                $pic_operations['rules'] = array([
                    'fileid' => $target,
                    'rule' => 'watermark/3/type/3/text/' . base64_encode($this->options['watermark_text']),
                ]);
                $request = $this->image_processing_request($url, $headers, $pic_operations); 
            }
        }

        if(isset($request['ProcessResults']['Object'])) {
            $return = array(
                'width' => $request['ProcessResults']['Object']['Width'],
                'height' => $request['ProcessResults']['Object']['Height'],
            );
            $format = strtolower($request['ProcessResults']['Object']['Format']);
            if($format && $format != $pathinfo['extension']) {
                $copykey = $pathinfo['dirname'] == '.' ? '/' : $pathinfo['dirname'] . '/';
                $copykey .= $pathinfo['filename'] . '.' . $format;
                $copy = $this->copy($target, $copykey);
                if($format == 'jpg' || $format == 'jpeg') {
                    $mime = 'image/jpeg';
                    $format = 'jpg';
                } else {
                    $mime = 'image/' . $format;
                }

                if($copy === true) {
                    $this->delete($target);
                    $return['old'] = $pathinfo['filename'] . '.' . $pathinfo['extension'];
                    $return['new'] = $pathinfo['filename'] . '.' . $format;
                    $return['mime'] = $mime;
                }
            }

            return $return;
        }

    }
   
    //检查是否需要进行图片处理
    public function is_image_processing($file) {
        if(!$this->options['image_style'] && 
            'off' == $this->options['watermark'] &&
            'off' == $this->options['image_compress']
        ) {
            return false;
        }
        $mime = mime_content_type($file);
        $mime = explode('/', $mime);
        return 'image' == $mime[0];
    }

    //盲水印提取
    public function get_watermark($target, $file) {
        if('off' == $this->options['watermark']) {
            return;
        }
        $pic_operations['is_pic_info'] = 0;
        if('image' == $this->options['watermark']) {
            $pic_operations['rules'] = array([
                'fileid' => '/watermark_view.png',
                'rule' => 'watermark/4/type/2/image/' . base64_encode('http://' . $this->host . '/watermark.png'),
            ]);
        }

        if('text' == $this->options['watermark'] && $this->options['watermark_text']) {
            $pic_operations['rules'] = array([
                'fileid' => '/watermark_view.png',
                'rule' => 'watermark/4/type/3/text/' . base64_encode($this->options['watermark_text']),
            ]);
        }
        $pic_operations = json_encode($pic_operations, JSON_UNESCAPED_UNICODE);

        return $this->upload($target, $file, [
            'Pic-Operations' => $pic_operations,
        ]);
    }
}
?>